function Moi(params) {
    //页面数据
    this.pageStorage = {};

    //事件
    this.event = {};

    this.ProductPictureShake = true;
    this.ProductShake = true;

    this.globalpopupLayer;
}

Moi.prototype.addEvent = function (name, fun, isDefault) {
    const self = this;
    if (!this.event[name]) {
        this.event[name] = {
            isExecute: true,
            default: false,
            defaultFunction: null,
            params: {},
            preventDefault(event) {
                //阻止默认
                self.event[name].default = false;
            },
            stopPropagation() {
                //阻止冒泡
                self.event[name].isExecute = false;
            },
            fun: []
        };
    }

    if (isDefault && fun) {
        this.event[name].default = true;
        this.event[name].defaultFunction = fun;
        return;
    }

    this.event[name].fun.push(fun);
};

Moi.prototype.onEvent = function (name, params) {
    const event = this.event[name];
    if (!event || event === undefined) {
        return params ? { params: params } : false;
    }
    event.params = params;
    let eventLength = 0;

    if (event.fun && event.fun.length) {
        while (event.isExecute) {
            event.fun[eventLength].call(this, event);
            eventLength++;
            if (eventLength === event.fun.length) {
                event.isExecute = false;
            }
        }
    }

    if (event.default) {
        event.defaultFunction.call(this, event);
    }

    //重置
    event.isExecute = true;

    return event;
};

// 移除事件
Moi.prototype.removeEvent = function (name) {
    // this.event[name] = null;
};

// 表单方法
Moi.prototype.form = function (id, rule) {
    //验证规则
    const copyRule = rule;

    // 获取fom接单
    const formNodes = $(id);

    //表单子元素
    const items = formNodes.find(`.mo-form-item`);

    //回调事件
    const callbackFu = {
        //获取input信息
        getInputValue: function (inputs, index) {
            const values = [];
            if (inputs.length) {
                for (let i = 0; i < inputs.length; i++) {
                    const inputNode = inputs[i];

                    //绑定焦点事件
                    inputNode.addEventListener("focus", function (params) {
                        callbackFu.hideError(index);
                    });

                    values.push({ value: inputNode.value.trim(), index: index });
                }
            }
            return values;
        },
        //获取所有value
        allValue: function () {
            const itemValues = {};
            for (let i = 0; i < items.length; i++) {
                const itemNode = $(items[i]);
                if (itemNode.attr("name")) {
                    // || `key_${i}`
                    const key = itemNode.attr("name");
                    var input = itemNode.find("input");
                    var textarea = itemNode.find("textarea");
                    itemValues[key] = callbackFu.getInputValue(input.length ? input : textarea, i);
                }
            }
            return itemValues;
        },

        //隐藏错误信息
        hideError: function (index) {
            const itemNode = $(items[index]);
            if (itemNode.hasClass("form-show-error")) {
                itemNode.removeClass("form-show-error");
            }
        },

        //显示错误
        showError: function (index, message) {
            const activeClas = "form-show-error";
            const itemNode = $(items[index]);
            const errorNode = itemNode.children(".mo-form-item-error");
            //初次错误追加元素
            if (!errorNode.length) {
                return itemNode.addClass(activeClas).append(`<div class="mo-form-item-error">${message}</div>`);
            }

            //二次错误设置class
            if (!itemNode.hasClass(activeClas)) {
                console.log("二次错误");
                errorNode.html(message);
                return itemNode.addClass(activeClas);
            }
        },

        //验证规则
        verifyRule(rules, value, index) {
            let returnStr = true;
            for (let i = 0; i < rules.length; i++) {
                const rule = rules[i];

                //验证必填

                if (rule.required && !value.trim()) {
                    callbackFu.showError(index, rule.message);
                    returnStr = false;
                    return;
                }

                //是否有自定义验证
                if (rule.validator) {
                    rule.validator(value, rules, function (msg) {
                        console.log(msg, index);
                        if (msg) {
                            callbackFu.showError(index, msg);
                            returnStr = false;
                        }
                    });
                }
            }

            return returnStr;
        },

        //验证所有
        allVerify: function () {
            let status = true;

            const allValues = callbackFu.allValue();
            const keys = Object.keys(allValues);
            for (let i = 0; i < keys.length; i++) {
                const key = keys[i];

                const value = allValues[key].map((el) => el.value).toString();
                const index = allValues[key].length && allValues[key][0].index;
                //验证数据
                if (copyRule[key] && !callbackFu.verifyRule(copyRule[key], value, index)) {
                    status = false;
                }
            }

            return status;
        },

        //验证
        verify: function (name) {
            const allValues = callbackFu.allValue();

            const keys = Object.keys(allValues);

            const key = name;

            const value = allValues[key].map((el) => el.value).toString();
            // const value = allValues[key].toString();

            //验证数据

            if (copyRule[key] && !callbackFu.verifyRule(copyRule[key], value, keys.indexOf(name))) {
                return false;
            }

            return true;
        }
    };

    return callbackFu;
};

//form value 数组变字符串
Moi.prototype.paramsValueString = function (obj) {
    var keys = Object.keys(obj);
    keys.forEach((key) => {
        obj[key] = obj[key].map((el) => el.value).toString();
    });
    return obj;
};

//显示加载框
Moi.prototype.nodeShowLoading = function (dom, str) {
    var selfDom = $(dom);
    var className = "mo-loading-warp";
    var old = selfDom.html();
    var style = "";
    if (str) {
        className = className + " " + str;
    }
    selfDom.addClass(className);
    if (str && str.indexOf("#") > -1) {
        style = `style="border-color:${str}; border-bottom-color: transparent;"`;
    }
    selfDom.html(`<div class="mo-loading" ${style}></div>`);
    return {
        //回调关闭加载样式
        close: function () {
            selfDom.removeClass(className);
            selfDom.html(old);
        }
    };
};

// //ajax
// Moi.prototype.ajax = function (option) {
//     $.ajax({
//         ...option
//     });
// };

//设置cookie
//这是有设定过期时间的使用示例：
//s20是代表20秒
//h是指小时，如12小时则是：h12
//d是天数，30天则：d30
Moi.prototype.setCookie = function (name, value, time, path, domain) {
    var strsec = getsec(time);
    var exp = new Date();
    exp.setTime(exp.getTime() + strsec * 1);
    document.cookie = name + "=" + encodeURIComponent(value) + ";expires=" + exp.toGMTString() + ";path=" + (path || "/") + ";domain=" + (domain || "");
};

function getsec(str) {
    var str1 = str.substring(1, str.length) * 1;
    var str2 = str.substring(0, 1);
    if (str2 == "s") {
        return str1 * 1000;
    } else if (str2 == "h") {
        return str1 * 60 * 60 * 1000;
    } else if (str2 == "d") {
        return str1 * 24 * 60 * 60 * 1000;
    }
}

//删除cookie
Moi.prototype.delCookie = function (cname, path, domain) {
    // var date = new Date();
    // date.setTime(date.getTime() +(-1*24*60*60*1000));
    // document.cookie = name + "=a; expires=" + date.toGMTString() + ";path=" + (path || "/") + ";domain=" + (domain || "");
    var d = new Date();
    d.setTime(d.getTime() + -1 * 24 * 60 * 60 * 1000);
    var expires = "expires=" + d.toUTCString();
    var path_ = "path=" + path || "/",
        domain_ = domain ? "domain=" + domain + ";" : ";";
    document.cookie = cname + "=''; " + domain_ + expires + "; " + path_;
};

//获取cookie
Moi.prototype.getCookie = function (name) {
    var arr,
        reg = new RegExp("(^| )" + name + "=([^;]*)(;|$)");
    if ((arr = document.cookie.match(reg))) return decodeURIComponent(arr[2]);
    else return null;
};

//获取链接参数
Moi.prototype.getUrlParam = function (name) {
    var reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)"); //构造一个含有目标参数的正则表达式对象
    var r = window.location.search.substr(1).match(reg); //匹配目标参数
    if (r != null) {
        r[2] = r[2].replace("+", " ");
        return decodeURIComponent(r[2]);
    }
    return ""; //返回参数值
};

//修改链接参数
Moi.prototype.changeURLArg = function (uri, key, value) {
    if (!value) {
        return uri;
    }
    var re = new RegExp("([?&])" + key + "=.*?(&|$)", "i");
    var separator = uri.indexOf("?") !== -1 ? "&" : "?";
    if (uri.match(re)) {
        return uri.replace(re, "$1" + key + "=" + value + "$2");
    } else {
        return uri + separator + key + "=" + value;
    }
};

/**
 * @description: 设置链接参数
 * @param {*} url 拦截
 * @param {*} params get参数
 * @return {*} url
 */
Moi.prototype.setUrlParams = function (url, params) {
    let newURL = url;
    const paramsKey = Object.keys(params);
    paramsKey.forEach((key) => {
        if (params[key] !== "") {
            newURL = this.changeURLArg(newURL, key, params[key]);
        }
    });
    return newURL;
};

//修改链接参数
Moi.prototype.addURLParam = function (url, key, value) {
    var replaceText = key + "=" + value;
    if (url.match("[?]")) {
        return url + "&" + replaceText;
    } else {
        return url + "?" + replaceText;
    }
};

//提示框
Moi.prototype.alert = function (options) {
    const template = `<div class="mo-confirm"><div class="mo-confirm-body"><div class="mo-title">${options.title}</div><div class="mo-handle"><div class="mo-handle-btn mo-handle-ok">${lang.general.yes}</div></div></div></div>`;
    const temp = $(template);
    // const closeNodes = temp.find(".mo-handle-close")[0];
    const okNodes = temp.find(".mo-handle-ok")[0];

    //关闭事件
    function close() {
        // closeNodes.removeEventListener("click", close, false);
        okNodes.removeEventListener("ok", ok, false);
        temp.remove();
    }

    //确定事件
    function ok() {
        options.ok && options.ok();
        close();
    }

    // closeNodes.addEventListener("click", close, false);
    okNodes.addEventListener("click", ok, false);

    $("body").append(temp);
};

//轻提示框
Moi.prototype.alertInfo = function ({ content = "", timer = 2000, type = "info", placement = "center", onClose }) {
    const alertTypesMap = {
        info: "",
        success:
            '<svg t="1658471413522" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="17451" width="200" height="200"><path d="M512 1024C229.180952 1024 0 794.819048 0 512S229.180952 0 512 0s512 229.180952 512 512-229.180952 512-512 512z m0-975.238095C256 48.761905 48.761905 256 48.761905 512s207.238095 463.238095 463.238095 463.238095 463.238095-207.238095 463.238095-463.238095S768 48.761905 512 48.761905z" fill="#25AA53" p-id="17452"></path><path d="M763.12381 329.142857c-9.752381-9.752381-24.380952-9.752381-34.133334 0l-292.571428 292.571429-134.095238-134.095238c-9.752381-7.314286-24.380952-7.314286-31.695239 2.438095-9.752381 7.314286-9.752381 21.942857-2.438095 31.695238l153.6 153.6c9.752381 7.314286 24.380952 7.314286 31.695238-2.438095l2.438096-2.438096c2.438095 0 4.87619-2.438095 4.87619-4.87619l302.32381-302.32381c9.752381-9.752381 9.752381-24.380952 0-34.133333z" fill="#25AA53" p-id="17453"></path></svg>',
        warn: '<svg t="1658471442639" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="17602" width="200" height="200"><path d="M512 1024C229.180952 1024 0 794.819048 0 512S229.180952 0 512 0s512 229.180952 512 512-229.180952 512-512 512z m0-975.238095C256 48.761905 48.761905 256 48.761905 512s207.238095 463.238095 463.238095 463.238095 463.238095-207.238095 463.238095-463.238095S768 48.761905 512 48.761905z" fill="#E88C4E" p-id="17603"></path><path d="M512.609524 268.190476c14.628571 0 24.380952 9.752381 24.380952 24.380953v316.952381c0 14.628571-9.752381 24.380952-24.380952 24.380952s-24.380952-9.752381-24.380953-24.380952V292.571429c0-14.628571 9.752381-24.380952 24.380953-24.380953zM488.228571 731.428571h48.761905v48.761905h-48.761905z" fill="#E88C4E" p-id="17604"></path></svg>',
        danger: '<svg t="1658471452213" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="17753" width="200" height="200"><path d="M512 1024C229.180952 1024 0 794.819048 0 512S229.180952 0 512 0s512 229.180952 512 512-229.180952 512-512 512z m0-975.238095C256 48.761905 48.761905 256 48.761905 512s207.238095 463.238095 463.238095 463.238095 463.238095-207.238095 463.238095-463.238095S768 48.761905 512 48.761905z" fill="#DB2739" p-id="17754"></path><path d="M702.171429 668.038095l-153.6-153.6 146.285714-146.285714c9.752381-9.752381 9.752381-24.380952 0-34.133333-9.752381-9.752381-24.380952-9.752381-34.133333 0l-146.285715 146.285714-153.6-153.6c-4.87619-4.87619-17.066667-2.438095-26.819047 7.314286s-12.190476 21.942857-7.314286 26.819047l153.6 153.6-146.285714 146.285715c-9.752381 9.752381-9.752381 24.380952 0 34.133333s24.380952 9.752381 34.133333 0l146.285714-146.285714 153.6 153.6c4.87619 4.87619 17.066667 2.438095 26.819048-7.314286s12.190476-21.942857 7.314286-26.819048z" fill="#DB2739" p-id="17755"></path></svg>'
    };
    const ANIMATION_TIMER = 1000,
        MODAL_ID = `mo-alert-info-model_${Date.now()}`;
    const html = `
       <div class="mo-alert-info-model mo-alert-info-model_${placement}" id="${MODAL_ID}">
          <div class="mo-alert-info-body" style="animation-duration: ${ANIMATION_TIMER}ms">
             ${alertTypesMap[type]}
             <span class="mo-alert-info-content">${content}</span>
          </div>
       </div>
    `;

    $(".mo-alert-info-model").remove();
    $(document.body).append(html);

    // 关闭
    setTimeout(() => {
        const $alertBody = $(`#${MODAL_ID} .mo-alert-info-body`);
        if (placement === "center") {
            $alertBody.addClass("mo-alert-info_close-center-animation");
        } else {
            $alertBody.addClass("mo-alert-info_close-top-animation");
        }

        setTimeout(() => {
            $(`#${MODAL_ID}`).remove();
            onClose && onClose();
        }, ANIMATION_TIMER - 80 /* 减去80ms，防止出现计时误差 */);
    }, timer + ANIMATION_TIMER);
};

// 消息框
Moi.prototype.message = function (options) {
    const defaultOption = {
        type: "success", // success，error，info
        content: "content",
        onClose: null,
        link: "",
        timer: 2000,
        ...options
    };
    let icon = "";

    switch (defaultOption.type) {
        case "success":
            icon = `<svg t="1641532926783" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="9539" width="200" height="200"><path d="M512 25.6a486.5408 486.5408 0 0 0-189.3248 934.592 486.528 486.528 0 0 0 378.6496-896.384A483.328 483.328 0 0 0 512 25.6m0-25.6A512 512 0 1 1 0 512 512 512 0 0 1 512 0z" fill="#29BB9D" p-id="9540"></path><path d="M274.092113 486.674451m9.050966 9.050967l162.917403 162.917402q9.050967 9.050967 0 18.101934l0 0q-9.050967 9.050967-18.101934 0l-162.917402-162.917403q-9.050967-9.050967 0-18.101933l0 0q9.050967-9.050967 18.101933 0Z" fill="#29BB9D" p-id="9541"></path><path d="M775.375724 350.881006m-9.050967 9.050967l-316.783838 316.783838q-9.050967 9.050967-18.101933 0l0.009051 0.009051q-9.050967-9.050967 0-18.101934l316.783838-316.783838q9.050967-9.050967 18.101933 0l-0.009051-0.009051q9.050967 9.050967 0 18.101934Z" fill="#29BB9D" p-id="9542"></path></svg>`;
            break;
        case "error":
            icon = `<svg t="1635319085856" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="29395" width="200" height="200">
        <path d="M512 512m-512 0a512 512 0 1 0 1024 0 512 512 0 1 0-1024 0Z" fill="#EE4550" p-id="29396"></path>
        <path d="M548.266667 512.341333l126.976 127.232a25.642667 25.642667 0 0 1-36.224 36.309334L512 548.650667l-126.976 127.232a25.642667 25.642667 0 0 1-36.224-36.309334l126.976-127.232-126.976-127.232a25.6 25.6 0 0 1 0.128-36.010666 25.6 25.6 0 0 1 36.138667 0l126.933333 126.933333 126.976-127.232a25.642667 25.642667 0 0 1 36.224 36.309333l-126.933333 127.232z" fill="#FFFFFF" p-id="29397"></path>
      </svg>`;
            break;
        case "info":
            icon = `<svg t="1635319120477" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="29528" width="200" height="200">
        <path
          d="M512 0a512 512 0 1 0 512 512 512 512 0 0 0-512-512z m31.552 757.824a52.096 52.096 0 0 1-35.648 13.696 53.952 53.952 0 0 1-36.544-13.568 47.488 47.488 0 0 1-15.616-37.888 48.832 48.832 0 0 1 15.104-36.352 51.2 51.2 0 0 1 37.056-14.72 50.368 50.368 0 0 1 51.2 51.2 47.872 47.872 0 0 1-15.424 37.696z m128-317.504a156.096 156.096 0 0 1-28.096 37.888q-16.256 15.936-58.432 53.632a238.208 238.208 0 0 0-18.688 18.688 75.904 75.904 0 0 0-10.432 14.72 72.448 72.448 0 0 0-5.312 13.376q-1.856 6.4-5.632 23.488a38.4 38.4 0 0 1-40.768 35.648 41.664 41.664 0 0 1-30.016-11.648 45.76 45.76 0 0 1-12.16-34.624 121.6 121.6 0 0 1 32.576-86.912 543.488 543.488 0 0 1 39.744-37.888q21.952-19.2 32-28.992a99.136 99.136 0 0 0 16.448-21.76 52.544 52.544 0 0 0 6.4-26.048 60.608 60.608 0 0 0-20.416-46.272 74.56 74.56 0 0 0-52.608-18.816 72.768 72.768 0 0 0-55.552 19.2 151.488 151.488 0 0 0-30.208 56.064q-11.648 38.4-44.224 38.4a43.456 43.456 0 0 1-32.384-13.568 41.344 41.344 0 0 1-13.184-29.312 123.776 123.776 0 0 1 20.928-65.984 160.896 160.896 0 0 1 60.992-55.36 192 192 0 0 1 93.632-21.952 199.872 199.872 0 0 1 87.744 18.368 142.272 142.272 0 0 1 58.816 49.856 122.304 122.304 0 0 1 20.736 68.544 105.984 105.984 0 0 1-11.84 51.2z"
          fill="#333333" p-id="29529"></path>
      </svg>`;
            break;
    }

    const template = `<div class=mo-modal><div class=mo-modal-mask></div><div class=mo-modal-body><div class=mo-modal-warp>${icon} <span class="message-text">${defaultOption.content}</span></div></div></div>`;
    const temp = $(template);
    $("body").append(temp);

    const modelBody = temp.find(".mo-modal-body");
    modelBody.addClass("animated bounceIn");

    setTimeout(() => {
        modelBody.addClass("animated bounceOut"); //取消动画
        setTimeout(function () {
            //关闭弹窗
            temp.remove();
            //是否存在链接跳转
            if (defaultOption.link) {
                window.location.href = defaultOption.link;
                return;
            }
            defaultOption.onClose && defaultOption.onClose.call(this, {});
        }, 500);
    }, defaultOption.timer);
};

//询问框
Moi.prototype.confirm = function (options) {
    const defaultOption = {
        title: "content",
        okText: lang.general.yes,
        cancelText: lang.general.no,
        ...options
    };

    const template = `<div class="mo-confirm"><div class="mo-confirm-body"><div class="mo-title">${defaultOption.title}</div><div class="mo-handle"><div class="mo-handle-btn mo-handle-ok">${defaultOption.okText}</div><div class="mo-handle-btn mo-handle-close">${defaultOption.cancelText}</div></div></div></div>`;
    const temp = $(template);
    const closeNodes = temp.find(".mo-handle-close")[0];
    const okNodes = temp.find(".mo-handle-ok")[0];

    //关闭事件
    function close() {
        closeNodes.removeEventListener("click", close, false);
        okNodes.removeEventListener("ok", ok, false);
        temp.find(".mo-confirm-body").addClass("animated bounceOut");
        setTimeout(function () {
            temp.remove();
        }, 500);
    }

    //关闭事件
    function ok() {
        options.ok && options.ok();
        close();
    }

    closeNodes.addEventListener("click", close, false);
    okNodes.addEventListener("click", ok, false);

    $("body").append(temp);

    temp.find(".mo-confirm-body").addClass("animated bounceIn");
};

//定位到元素

Moi.prototype.windowPositionNode = function (id) {
    $("html,body").animate({ scrollTop: $(id).offset().top }, 200);
};

//文字提示框
Moi.prototype.tooltip = function (options) {
    const defaultOption = {
        placement: "left",
        el: "",
        timer: 1000,
        space: 0,
        content: "",
        ...options
    };

    const cssOption = {
        opacity: 1,
        transform: "scale(1)",
        visibility: "visible"
    };

    const template = `<div class="mo-tooltip mo-tooltip-placement-${defaultOption.placement}">
<div class="mo-tooltip-content">
<div class="mo-tooltip-arrow"><span class="mo-tooltip-arrow-content"></span></div>
<div class="mo-tooltip-inner" role="tooltip">${defaultOption.content}</div>
</div>
</div>`;
    const temp = $(template);

    const node = $(defaultOption.el);

    const top = node.offset().top;
    const width = node.width();
    const height = node.height();
    const left = node.offset().left;

    //追加页面元素
    $("body").append(temp);

    const tipWidth = temp.innerWidth();
    const tipHeight = temp.innerHeight();

    switch (defaultOption.placement) {
        case "left":
            temp.css({
                ...cssOption,
                left: left - tipWidth - defaultOption.space,
                top: top - Math.floor(height / 2)
            });
            break;
        case "right":
            temp.css({
                ...cssOption,
                left: left + width + defaultOption.space,
                top: top - Math.floor(height / 2)
            });
            break;
        case "top":
            temp.css({
                ...cssOption,
                left: left,
                top: top - tipHeight - defaultOption.space
            });
            break;
        case "bottom":
            temp.css({
                ...cssOption,
                left: left,
                top: top + height + defaultOption.space
            });
            break;
    }

    setTimeout(function () {
        temp.css({
            opacity: 0,
            transform: "scale(0)"
        });
        setTimeout(function () {
            temp.remove();
        }, 500);
    }, 1000);
};

//post 请求
Moi.prototype.ajax = function (option) {
    const slef = this;
    option.url = `/homeapi${option.url}`;
    // console.log(option)
    $.ajax({
        headers: {
            // Token: slef.getCookie("Token"),
            "Content-Type": "application/json;charset=UTF-8"
        },
        // data: JSON.stringify(data),
        dataType: "json",
        ...option
    });
};

//post 请求
Moi.prototype.post = function (url, data, option) {
    url = `/homeapi/${url}`;
    this.ajax({
        url: url,
        type: "post",
        data: JSON.stringify(data),
        ...option
    });
};

//get 请求
Moi.prototype.get = function (url, data, option) {
    this.ajax({
        url: url,
        type: "get",
        data: data,
        ...option
    });
};

//del 请求
Moi.prototype.del = function (url, data, option) {
    this.ajax({
        url: url,
        type: "delete",
        data: JSON.stringify(data),
        ...option
    });
};

//设置页面数据
Moi.prototype.setPageStorage = function (key, option) {
    this.pageStorage[key] = JSON.parse(JSON.stringify(option));
};

//获取页面数据
Moi.prototype.getPageStorage = function (key, defaultParams) {
    return this.pageStorage[key] || defaultParams;
};

//获取页面数据
Moi.prototype.quantity = function (option) {
    const quantityDom = option.dom;
    const valueDom = quantityDom.find(".product-calculator-value");
    const handleDom = quantityDom.find(".product-calculator-handle");
    handleDom.click(function () {
        const type = $(this).data("type");
        let value = Number(valueDom.html());

        if (type === "reduce" && value !== 1) {
            valueDom.html(--value);
        }
        if (type === "add") {
            valueDom.html(++value);
        }

        option.change && option.change.call(this, { value: value, type: type });
    });
};

//监听A标签调整
Moi.prototype.bindRedirectHref = function (node) {
    const self = this;
    const theme_id = this.getUrlParam("theme_id");
    // document.get
    if (theme_id) {
        const ADOM = node || $("a");
        ADOM.on("click", function (e) {
            e.preventDefault();
            const href = $(this).attr("href");

            if (href === "javascript:;") {
                // self.alertInfo({ content: $(this).data("tips") || "请添加" });
                return;
            }

            if (href.indexOf("?") === -1) {
                location.href = `${href}?theme_id=${theme_id}`;
            } else {
                location.href = `${href}&theme_id=${theme_id}`;
            }
        });
    }
};

//跳转页面
Moi.prototype.href = function (URL) {
    let url = URL;
    const theme_id = this.getUrlParam("theme_id");
    //是否有主题id
    if (theme_id) {
        if (url) {
            const splitStr = url.indexOf("?") === -1 ? "?" : "&";
            url = `${URL}${splitStr}theme_id=${theme_id}`;
        } else {
            this.alertInfo({ content: "请添加链接" });
            return false;
        }
    }
    location.href = url;
};

Moi.prototype.appendLoading = function ({ size = 50, container, theme, position } = {}) {
    $(container).css("pointer-events", "none");
    const style = document.createElement("style");
    style.innerHTML = `
   #common_tool-loading {
      position: ${position ? position : container ? "absolute" : "fixed"};
      top: 0; left: 0; bottom: 0; right: 0;
      background: ${theme ? (theme === "dark" ? "rgba(0, 0, 0, .8)" : "#ffffffe6") : ""};
      display: flex;
      align-items: center;
      justify-content: center;
      transition: opacity .2s linear;
   }
   #common_tool-loading svg {
      animation: common_tool-loading-spin 1s linear infinite;
      fill: ${theme && theme === "dark" ? "#fff" : "#666"}
   }
   @keyframes common_tool-loading-spin {
      from { transform: rotate(0deg); }
      to { transform: rotate(360deg); }
   }
`;
    const loading = `
   <div id="common_tool-loading">
      <svg width="${size}" height="${size}" t="1644634233141" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="11473"><path d="M270.4 214.4C336 160 420 128 512 128c212 0 384 172 384 384h64c0-247.2-200.8-448-448-448-107.2 0-205.6 37.6-282.4 100l40.8 50.4z" p-id="11474"></path></svg>
   </div>
`;
    document.head.appendChild(style);
    $(container || "body").append(loading);
};

Moi.prototype.removeLoading = function (container) {
    $(container).css("pointer-events", "");
    const $loading = $(`${container || "body"} #common_tool-loading`).css("opacity", 0);
    setTimeout(() => $loading.remove(), 200);
};
Moi.prototype.popup = function (option) {
    const defaultOption = { load: true, animated: true, ...option };
    const temp = $(`<div class="mo-popup"><div class="mo-popup-mask popup-claer"></div><div class="mo-popup-body"><div class="mo-popup-content"></div></div></div>`);
    const content = temp.find(".mo-popup-content");
    let load = false;

    if (defaultOption.load) {
        load = moi.nodeShowLoading(content, "mo-loading-black");
    }

    const returnOption = {
        temp: temp,
        load: load,
        showLoading() {
            returnOption.load = moi.nodeShowLoading(temp.find(".mo-popup-content"), "mo-loading-black");
            return load;
        },
        hideLoading() {
            returnOption.load && returnOption.load.close();
        },
        close(callback) {
            defaultOption.animated && content.addClass("animated bounceOutUp");
            setTimeout(function () {
                temp.remove();
                callback && callback();
            }, 800);
        },
        addContent(html) {
            defaultOption.load && load.close();
            content.append(html);
            defaultOption.animated && content.addClass("animated bounceInDown");
            const closeNodes = temp.find(".popup-claer");

            closeNodes.on("click", function () {
                returnOption.close();
            });
        }
    };

    returnOption.showLoading();
    $("body").append(temp);

    return returnOption;
};

Moi.prototype.createScript = function (URL, callback) {
    //当前url的script
    const currentScript = $("script[src='" + URL + "']");

    //是否存在；存在直接执行
    if (currentScript.length) {
        callback && callback();

        return;
    }

    //创建一个script标签
    const script = document.createElement("script");
    script.setAttribute("type", "text/javascript");
    script.setAttribute("src", URL);
    script.onload = function () {
        callback && callback();
    };
    document.body.appendChild(script);
};

/**
 *
 * @param {*} videoId 视频id
 * @param {*} vedioContainer 视频容器
 * @param {*} height 视频高度，默认300
 * @param {*} width 视频宽度，默认全屏
 * @param {*} config 配置文件，播放参数
 */
Moi.prototype.youtubeVideoPlay = function (vedioContainer, option) {
    if (!vedioContainer) throw "视频容器不能为空";
    this.createScript("https://www.youtube.com/iframe_api", () => {
        const timer = setInterval(() => {
            if (window.YT && YT.Player) {
                clearInterval(timer);
                const player = new YT.Player(vedioContainer, option);
                option.success && option.success.call(this, player);
            }
        }, 300);
    });
};

//弹出商品预览
Moi.prototype.popupProductPicture = function (option) {
    if (!this.ProductPictureShake) {
        return false;
    }
    const theme_id = this.getUrlParam("theme_id");
    // from
    this.globalpopupLayer = this.popup();
    this.globalpopupLayer.addContent(`<div class="quick-iframe-wrap"><div class="quick-iframe-wrap-loading"></div><iframe class="quick-iframe" scrolling="no" id="quick-iframe" src="/products/${option.handle}?&quick_view=1&data_from=${option.data_from}"></iframe></div>`);
};

//弹出商品选择加入购物车
Moi.prototype.popupProduct = function (option) {
    if (!this.ProductShake) {
        return false;
    }

    const self = this;

    const lang = window.lang;

    const popupLayer = this.popup();
    this.ProductShake = false;
    getProductInfo(option.handle, function (ret) {
        const retData = ret.data.product;
        self.ProductShake = true;
        //添加购物车
        function addCart(load) {
            moi.ajax({
                url: "/cart/add",
                type: "post",
                data: JSON.stringify({
                    product_id: retData.id,
                    sku_code: retData.variant.sku_code,
                    quantity: 1,
                    data_from: self.getUrlParam("data_from")
                }),
                complete() {
                    load && load.close();
                },
                success: function (data) {
                    if (!data.code) {
                        temp.remove();
                        miniCart();
                        const unm = parseInt($("#cart_number").text() || 0) + 1;
                        $("#cart_number")
                            .show()
                            .html(unm > 99 ? 99 + "+" : unm);
                        $(".minicart").addClass("minicart_on");
                        oemasaasAddCardScriptScope && oemasaasAddCardScriptScope();
                    } else {
                        return self.alert({
                            title: data.msg
                        });
                    }
                }
            });
        }

        if (retData.variants.length === 1) {
            popupLayer.close();
            addCart();
            return;
        }

        engine
            .parseAndRender($("#omesaas-popup-addPurchase").html(), {
                product: retData,
                lang: lang
            })
            .then(function (html) {
                popupLayer.addContent(html);
                const temp = popupLayer.temp;
                const productDetail = new omesaasProduct({
                    product: retData,
                    id: temp.find("#buy-sku-option")
                });

                self.quantity({
                    dom: temp.find(".mo-quantity"),
                    change(val) {
                        productDetail.setSelectedVal({ quantity: val.value });
                    }
                });

                //加入购物车
                temp.find("[data-type='cart']").click(function () {
                    if (!productDetail.verifyOption("cart")) {
                        return false;
                    }

                    var load = self.nodeShowLoading(this, "mo-loading-black");
                    productDetail.addCart(
                        function () {
                            load.close();
                        },
                        function (data) {
                            if (!data.code) {
                                popupLayer.close(function () {
                                    $(".minicart").addClass("minicart_on");
                                });
                            } else {
                                return self.alert({
                                    title: data.msg
                                });
                            }
                        }
                    );
                });
                //直接购买
                temp.find("[data-type='buy_now']").click(function () {
                    if (!productDetail.verifyOption("buy")) {
                        return false;
                    }

                    var load = self.nodeShowLoading(this);

                    productDetail.buynow(
                        function () {
                            load.close();
                        },
                        function (ret) {
                            if (!ret.code) {
                                self.href(ret.data.checkout_url);
                            } else {
                                return self.alert({
                                    title: ret.msg
                                });
                            }
                        }
                    );
                });
            });
    });
};

//过滤设置当前语言
Moi.prototype.getLanguage = function (language) {
    if (language[oemcart_website_language]) {
        return language[oemcart_website_language];
    }
    return "";
};

Moi.prototype.formatDate = function (dateTime) {
    let temptTime = new Date(dateTime.getTime());
    // 周几
    let weekday = temptTime.getDay() || 7;
    // 周1+5天=周六
    temptTime.setDate(temptTime.getDate() - weekday + 1 + 5);
    let firstDay = new Date(temptTime.getFullYear(), 0, 1);
    let dayOfWeek = firstDay.getDay();
    let spendDay = 1;
    if (dayOfWeek != 0) spendDay = 7 - dayOfWeek + 1;
    firstDay = new Date(temptTime.getFullYear(), 0, 1 + spendDay);
    let d = Math.ceil((temptTime.valueOf() - firstDay.valueOf()) / 86400000);
    let result = Math.ceil(d / 7);
    return result;
};

//格式化时间
Moi.prototype.formatDate = function (date, format) {
    let we = date.getDay(); // 星期
    let z = this.getWeek(date); // 周
    let qut = Math.floor((date.getMonth() + 3) / 3).toString(); // 季度
    const opt = {
        "Y+": date.getFullYear().toString(), // 年
        "m+": (date.getMonth() + 1).toString(), // 月(月份从0开始，要+1)
        "d+": date.getDate().toString(), // 日
        "H+": date.getHours().toString(), // 时
        "M+": date.getMinutes().toString(), // 分
        "S+": date.getSeconds().toString(), // 秒
        "q+": qut // 季度
    };
    // 中文数字 (星期)
    const week = {
        0: "日",
        1: "一",
        2: "二",
        3: "三",
        4: "四",
        5: "五",
        6: "六"
    };
    // 中文数字（季度）
    const quarter = {
        1: "一",
        2: "二",
        3: "三",
        4: "四"
    };
    if (/(W+)/.test(format)) format = format.replace(RegExp.$1, RegExp.$1.length > 1 ? (RegExp.$1.length > 2 ? "星期" + week[we] : "周" + week[we]) : week[we]);
    if (/(Q+)/.test(format)) format = format.replace(RegExp.$1, RegExp.$1.length == 4 ? "第" + quarter[qut] + "季度" : quarter[qut]);
    if (/(Z+)/.test(format)) format = format.replace(RegExp.$1, RegExp.$1.length == 3 ? "第" + z + "周" : z + "");
    for (let k in opt) {
        let r = new RegExp("(" + k + ")").exec(format);
        // 若输入的长度不为1，则前面补零
        if (r) format = format.replace(r[1], RegExp.$1.length == 1 ? opt[k] : opt[k].padStart(RegExp.$1.length, "0"));
    }
    return format;
};

//生成随机数
Moi.prototype.randomInteger = function (minNum, maxNum) {
    switch (arguments.length) {
        case 1:
            return parseInt(Math.random() * minNum + 1, 10);
        case 2:
            return parseInt(Math.random() * (maxNum - minNum + 1) + minNum, 10);
        default:
            throw new Error("仅允许传入1~2个参数");
    }
};
//时区时间时间戳格式
Moi.prototype.formatZoneDate = function (value, format) {
    if (!value) {
        return "";
    }
    const sys_time = oemcart_time_zone;
    const reg = RegExp(/-/); //这儿注意有坑。。如果包含了-则不需要处理如果包含了+需要加上-, 后端php无法处理这个问题所以这儿反向判断了。。
    var data = 0;
    if (sys_time.indexOf("-") > -1 || sys_time.indexOf("+") > -1) {
        data = reg.test(sys_time) ? Number(sys_time.split(/[-|+]/)[1]) : -Number(sys_time.split(/[-|+]/)[1]);
    }
    const timeZone = parseInt(new Date().getTimezoneOffset() / 60) + parseInt(data);
    return this.formatDate(new Date(timeZone * 60 * 60 * 1000 + value * 1000), format);
};

//节流
Moi.prototype.throttle = function (func, wait) {
    //之前的时间戳
    let old = 0;
    return function () {
        //获取当前的时间戳
        let now = new Date().valueOf();
        if (now - old > wait) {
            //立即执行
            func.apply(this, arguments);

            old = now;
        }
    };
};

document.addEventListener("changeCartNum", function (event) {
    var num = event.detail.num;
    if (num > 99) {
        num = "99+";
    }
    if (num) {
        $("#cart_number").show().html(num);
    } else {
        $("#cart_number").hide();
    }
});

Moi.prototype.changeCartNumber = function (num) {
    this.setPageStorage("cart_number", num);
    const event = new CustomEvent("changeCartNum", {
        detail: {
            num: num
        }
    });
    document.dispatchEvent(event);
};

Moi.prototype.showMiniCart = function () {
    $(".minicart").addClass("minicart_on");
};
/**
 * @description: 预览图片
 * @param {*} urls 图片集合
 * @param {*} index 当前预览
 * @param {*} self 点击元素
 * @return {*}
 */
Moi.prototype.pictureImages = function (urls, index, self) {
    const tempHtml = $(`
<div class="view-picture">
<div class="view-picture-swiper" id="picture-swiper-container">
  <ul class="swiper-wrapper" style="width:100%"></ul>
</div>
<div class="view-picture-operate">
  <div class="operate-arrow-right" id='picture-swiper-prev'>
    <svg t="1635160440262" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1353" width="20" height="20"><path d="M511.609097 961.619254" p-id="1354"></path><path d="M360.749204 511.010463 360.749204 511.010463l382.080022-382.074905c14.762215-14.788821 14.762215-38.777165 0-53.585429-14.812357-14.788821-38.799678-14.788821-53.607942 0L283.415908 481.201553c-1.107217 0.867764-2.190899 1.824555-3.206018 2.843768-14.788821 14.808264-14.788821 38.795585 0 53.585429l408.226518 408.230612c14.808264 14.807241 38.795585 14.807241 53.584406 0 14.785751-14.767332 14.785751-38.754652 0-53.562916L360.749204 511.010463 360.749204 511.010463zM360.749204 511.010463" p-id="1355"></path></svg>
  </div>
  <div class="operate-arrow-close" id="operate-close">
    <svg t="1633405599567" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1984" width="20" height="20"><path d="M453.44 512L161.472 220.032a41.408 41.408 0 0 1 58.56-58.56L512 453.44 803.968 161.472a41.408 41.408 0 0 1 58.56 58.56L570.56 512l291.968 291.968a41.408 41.408 0 0 1-58.56 58.56L512 570.56 220.032 862.528a41.408 41.408 0 0 1-58.56-58.56L453.44 512z" p-id="1985"></path></svg>
  </div>
  <div class="operate-arrow-left" id='picture-swiper-next'>
    <svg t="1633330597342" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2631" width="20" height="20"><path d="M765.7 486.8L314.9 134.7c-5.3-4.1-12.9-0.4-12.9 6.3v77.3c0 4.9 2.3 9.6 6.1 12.6l360 281.1-360 281.1c-3.9 3-6.1 7.7-6.1 12.6V883c0 6.7 7.7 10.4 12.9 6.3l450.8-352.1c16.4-12.8 16.4-37.6 0-50.4z" p-id="2632"></path></svg>
  </div>
</div>
</div>
`);
    let swiperSlideHtml = "";

    for (let i = 0; i < urls.length; i++) {
        swiperSlideHtml += `<li class="swiper-slide"><img src="${urls[i]}"></li>`;
    }

    tempHtml.find(".swiper-wrapper").append(`<li class="swiper-slide"><img src="${urls[index]}"></li>`);

    const top = self.offset().top - $(document).scrollTop();
    const left = self.offset().left;
    const height = self.height();
    const width = self.width();

    tempHtml.css({ height: height, top: top, left: left, width: width, opacity: 0.1 });
    $("body").append(tempHtml);

    setTimeout(function () {
        tempHtml.css({ height: "100%", top: 0, left: 0, width: "100%", opacity: 1 });
    }, 100);

    setTimeout(function () {
        tempHtml.css({ backgroundColor: "rgba(0, 0, 0, 0.6)" });

        tempHtml.addClass("view-picture-operate-show");

        tempHtml.find(".swiper-wrapper").html(swiperSlideHtml);

        new Swiper("#picture-swiper-container", {
            loop: false,
            initialSlide: index,
            autoHeight: true,
            navigation: {
                nextEl: "#picture-swiper-next",
                prevEl: "#picture-swiper-prev"
            }
        });
    }, 800);

    tempHtml.find("#operate-close").click(function () {
        tempHtml.addClass("view-picture-operate-hide");
        tempHtml.css({ opacity: 0.1 });
        setTimeout(function () {
            tempHtml.remove();
        }, 400);
    });
};

window.moi = new Moi();
